package com.fot.core.listener;

import com.alibaba.fastjson.JSON;
import com.fot.core.Message;
import org.slf4j.MDC;
import org.springframework.aop.framework.AopProxyUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;

/**
 * @author 殷豪
 */
public interface RedisMQListener<T extends Message> {
    void onMessage(T message);

    default void processMessage(String message) {
        T msg = buildMessage(message);
        try {
            MDC.put("traceId", msg.getTransactionNo());
            onMessage(msg);
        }finally {
            MDC.clear();
        }
    }

    default T buildMessage(String message) {
        Type type = deserializable();
        return JSON.parseObject(message, type);
    }

    default Type deserializable() {
        Class<?> targetClass = AopProxyUtils.ultimateTargetClass(this);
        Type matchedGenericInterface = null;
        while (Objects.nonNull(targetClass)) {
            Type[] interfaces = targetClass.getGenericInterfaces();
            for (Type type : interfaces) {
                if (type instanceof ParameterizedType
                        && Objects.equals(((ParameterizedType) type).getRawType(), RedisMQListener.class)) {
                    matchedGenericInterface = type;
                    break;
                }
            }
            targetClass = targetClass.getSuperclass();
        }
        if (Objects.isNull(matchedGenericInterface)) {
            return Object.class;
        }
        Type[] actualTypeArguments = ((ParameterizedType) matchedGenericInterface).getActualTypeArguments();
        if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) {
            return actualTypeArguments[0];
        }
        return Object.class;
    }
}
